﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Collections;
using MySql.Data.MySqlClient;

/// <summary>
/// Descripción breve de GestorDeTransacciones
/// </summary>
public class GestorDeTransacciones
{
    #region Atributos

    public MySqlConnection miConexion;
    protected ArrayList miListaDeTablas;

    protected Usuario usuarioBloqueador;
    private object syncRoot;
    private Conexion conexion;

    #endregion

    #region Constructor

    public GestorDeTransacciones()
    {
        try
        {
            conexion = new Conexion();

            this.miConexion = conexion.dameConexion();
            this.miListaDeTablas = new ArrayList();

            this.usuarioBloqueador = null;

            this.syncRoot = new object();
        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
    }

    public GestorDeTransacciones(ArrayList pListaTablas)
    {
        try
        {
            conexion = new Conexion();

            this.miConexion = conexion.dameConexion();
            this.miListaDeTablas = pListaTablas;

            this.usuarioBloqueador = null;

            this.syncRoot = new object();
        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
    }

    #endregion

    #region Consultas

    /**
         * \brief Consulta la conexion comun para todos los gestores de aplicacion         
         */
    internal MySqlConnection dameMiConexion()
    {
        return this.miConexion;
    }
    /**
     * \brief Consulta la lista de Tablas comun para todos los gestores de aplicacion         
     */
    internal ArrayList dameMiListaTablas()
    {
        return this.miListaDeTablas;
    }
    /**
     * \brief Consulta si se un gestor esta bloqueado o no
     */
    internal void autorizarTransaccion(Usuario pUsuario)
    {
        while (!this.bloquearGestor(pUsuario))
        {
            System.Threading.Thread.Sleep(500);
        }
    }

    /**
     * \brief Consulta si se un gestor esta bloqueado o no
     */
    private bool bloquearGestor(Usuario pUsuario)
    {
        lock (syncRoot)
        {
            if (this.usuarioBloqueador != null && !pUsuario.Equals(this.usuarioBloqueador)) return false;
            else
            {
                this.usuarioBloqueador = pUsuario;

                return true;
            }
        }
    }
    /**
    * \brief Desbloquea el gestor
    */
    private void desbloquearGestor()
    {
        this.miListaDeTablas.Clear();
        this.usuarioBloqueador = null;
    }

    #endregion

    #region Metodos de insercion y modificacion

    public void ejecutarTransaccion()
    {
        MySqlTransaction transaccion = null;

        try
        {

            //Preparamos la transaccion
            transaccion = this.conexion.PrepararTransaccion(this.miConexion);

            foreach (SuperT tabla in this.miListaDeTablas)
            {
                tabla.confirmarCambiosBBDD(transaccion);
            }

            //Finalizamos la transaccion
            this.conexion.ConfirmarTransaccion(transaccion, this.miConexion);

            foreach (SuperT tabla in this.miListaDeTablas)
            {
                tabla.confirmarCambiosDataTable();
            }

            this.desbloquearGestor();
        }
        catch (Exception)
        {
            this.conexion.DeshacerTransaccion(transaccion, this.miConexion);

            throw new Exception("Error: Método ejecutarTransaccion; Clase GestorDeTransacciones.");
        }
    }

    public void deshacerTransaccion()
    {
        foreach (SuperT tabla in this.miListaDeTablas)
            tabla.deshacerCambios();

        this.desbloquearGestor();
    }

    #endregion
}